# install.packages("tidyverse");
# install.packages("rgdal");
library(tidyverse)
require("maps")
library(geosphere)
library(stringr)
library(rgdal)
library(caret)
library(lubridate)
if (!require(ggmap)) { install.packages('ggmap'); require(ggmap) }
path.to.csv <- '../Milestone 2/Seattle_Police_Department_911_Incident_Response_Oct17.csv'
spd.911 <- read.csv(path.to.csv, TRUE)
spd.911$clearance_date_ts = as.POSIXct(strptime(spd.911$Event.Clearance.Date, "%m/%d/%Y %I:%M:%S %p"))
spd.911$clearance_date_date = as.Date(spd.911$clearance_date_ts)
# View(spd.911)
# path to the FOLDER with the .shp file in it. the second param is the name of the .shp file
# seattle <- readOGR(dsn = path.expand("~/documents/INFO370/project-teamname-v2/maps-api-test"), layer = "Seattle_City_Limits")
# usa <- map_data("state")
# data <- merge(usa, spd.911)
here_long <-  -122.30
here_lat <- 47.66
seattle = get_map(location = c(here_long, here_lat), zoom = 13, maptype = 'roadmap')
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=47.66,-122.3&zoom=13&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
spd.911 <- spd.911 %>% 
             rowwise() %>% 
             mutate(dist=distVincentyEllipsoid(c(Longitude, Latitude), c(here_long, here_lat)))              
nrow(spd.911)
[1] 20197
descriptions <- c("STRONG ARM ROBBERY", "PERSON WITH A WEAPON (NOT GUN)", "HAZARDS", "HARRASMENT, THREATS", "FIGHT DISTURBANCE", "CRISIS COMPLAINT - GENERAL", "ARMED ROBBERY")
data.ped <- spd.911 %>% filter(str_detect(Event.Clearance.Description, paste(descriptions, collapse="|")))
# data.ped <- data.now
nrow(data.ped)
[1] 1068
data.now <- data.ped %>% filter(clearance_date_ts < '2017-10-31 00:00:00')
nrow(data.now)
[1] 1068
                  
data.here <- data.now %>% filter(dist < 4600)
data <- data.here
nrow(data)
[1] 154
# View(data)
ggmap(seattle) +
   geom_point(data = data, aes(x = Longitude, y = Latitude), colour = "red", alpha = 0.75)

  #coord_map()
freq_by_desc <- table(droplevels(data$Event.Clearance.Description))
# View(freq_by_desc)
ggplot(as.data.frame(freq_by_desc), 
       aes(x = Var1, y = Freq)) +
       geom_bar(stat = 'identity') +# create bar plot
    coord_flip()

#Traffic related calls, suspicious circumstances, and disturbances are the the most significant threats to pedestrations
        
ggmap(seattle) +
  geom_point(data = data, aes(x = Longitude, y = Latitude, group = Event.Clearance.Description, color = Event.Clearance.Description), alpha = 0.5) +
  facet_wrap(~ Event.Clearance.Description) +
  theme(axis.ticks = element_blank(), 
        axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        legend.position = "none"
        )

# selecting just ID and location data
df_loc <- data %>% dplyr::select(CAD.CDW.ID, Longitude, Latitude)
# figuring out number of clusters
wss <- c()
# clusters 1 to 15
for (i in 1:15) {
  wss[i] <- sum(kmeans(df_loc, centers=i)$withinss)
}
plot(1:15, wss, type="b", xlab="Number of Clusters",
  ylab="Within groups sum of squares")

# fitting model
fit <- kmeans(df_loc, 10)
fit$centers # look at cluster sizes and means. want clusters to be about equal size
   CAD.CDW.ID Longitude Latitude
1     2114598 -122.3178 47.65411
2     2109759 -122.3121 47.65562
3     2111482 -122.3199 47.65574
4     2115977 -122.3118 47.65820
5     2117842 -122.3182 47.65687
6     2120071 -122.3184 47.65099
7     2107842 -122.3248 47.65292
8     2123882 -122.3193 47.65530
9     2112892 -122.3230 47.66317
10    2105812 -122.3212 47.66055
fit$cluster
  [1] 10 10 10 10 10 10 10 10 10 10 10 10 10  7  7  7  7  7  7  7  7  7  7  7  7  7  7  2  2  2  2  2  2
 [34]  9  2  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  3  3  3  9  9  9  9  9  9  9  9  9  1
 [67]  1  1  1  1  1  1  1  1  1  1  1  1  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  5  5  5  5
[100]  5  5  5  5  5  5  5  5  5  5  5  5  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6
[133]  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8
cluster.size <- data.frame(1:10, fit$size)
cluster.size
ggplot(data = cluster.size, aes(x = X1.10, y = fit.size)) +
  geom_bar(stat = 'identity')

ggplot()

ggmap(seattle) +
  geom_point(data = as.data.frame(fit$centers), aes(x = Longitude, y = Latitude), alpha = 0.5)

# looking at cluster means
aggregate(df_loc, by=list(fit$cluster), FUN=mean)
df_loc
# adding data back into dataframe 
# df_loc <- df_loc %>% mutate(cluster = fit$cluster) 
data$cluster <- fit$cluster
# View(data)
# timestamp ->  year  month day hour  minute
# sector -> to factor (there are 17 sectors)
# beat -> to factor (there are 3 beats per sector)
# clean the data a bit more
data$event_clearance_ts = as.POSIXct(strptime(data$Event.Clearance.Date, "%m/%d/%Y %I:%M:%S %p"))
data$event_clearance_date = as.Date(data$event_clearance_ts)
data$event_clearance_month = month(ymd_hms(as.character(data$event_clearance_ts)))
data$event_clearance_day = weekdays(data$event_clearance_date)
data$event_clearance_hr = hour(ymd_hms(as.character(data$event_clearance_ts)))
data$event_clearance_mn = minute(ymd_hms(as.character(data$event_clearance_ts)))
data$Initial.Type.Group = factor(data$Initial.Type.Group)
data$Event.Clearance.Group = factor(data$Event.Clearance.Group)
data$Zone.Beat = factor(data$Zone.Beat)
data$District.Sector = factor(data$District.Sector)
data$event_clearance_day = factor(data$event_clearance_day)
data
col.names <- paste(c(
  "Event.Clearance.Code"
  , "cluster"
  , "Census.Tract"
  , "event_clearance_day"
  , "Event.Clearance.Group"
  , "Event.Clearance.SubGroup"
  , "District.Sector"
  , "Zone.Beat"
  #, "event_clearance_ts"
  # ,"Incident.Location"
  , "event_clearance_hr"
  , "event_clearance_mn"
  , "event_clearance_month" 
  , "Hundred.Block.Location"
  ), collapse="|")
cols <- grep(col.names, colnames(data))
cols
 [1]  4  6  7  9 10 11 12 23 26 27 28 29
# corr_matrix <- cor(data[,cols]) # correlations between all predictor vars
# corr_matrix
# cutoff <- 0.5 # should be higher in practice
# highly_corr <- findCorrelation(corr_matrix, cutoff=cutoff)
# print(colnames(spd.911)[highly_corr]) # age is highly correalted with pregnant
train.data <- select(data, cols)
train.data
# data <- data %>% droplevels()
# grep("Hundred.Block.Location", colnames(train.data), invert = T)
predictors <- grep("Hundred.Block.Location", colnames(train.data), invert = T)
outcome <- grep("Hundred.Block.Location", colnames(train.data))
# train.data[,predictors]
frame <- data.frame(train.data[,predictors])
frame
out.factor <- train.data$Hundred.Block.Location
as.vector(out.factor)
  [1] "43XX BLOCK OF 15 AV NE"                 "24XX BLOCK OF E LOUISA ST"             
  [3] "FREMONT BR / SB"                        "48XX BLOCK OF SAND POINT WY NE"        
  [5] "42XX BLOCK OF UNIVERSITY WY NE"         "21XX BLOCK OF N NORTHLAKE WY"          
  [7] "14XX BLOCK OF NE 43 ST"                 "BRIDGE WY N / N 38 ST"                 
  [9] "8XX BLOCK OF NE 95 ST"                  "14XX BLOCK OF NE 43 ST"                
 [11] "17XX BLOCK OF N 45 ST"                  "NE 54 ST / 21 AV NE"                   
 [13] "6XX BLOCK OF N 50 ST"                   "AURORA BR / SB"                        
 [15] "FAIRVIEW AV N / ALOHA ST"               "77XX BLOCK OF SAND POINT WY NE"        
 [17] "11XX BLOCK OF N 81 ST"                  "AURORA AV N / GARFIELD ST"             
 [19] "SAND POINT WY NE / 40 AV NE"            "55XX BLOCK OF 12 AV NE"                
 [21] "BRIDGE WY N / AURORA BR"                "3 AV NW / NW 45 ST"                    
 [23] "NE 43 ST / UNIVERSITY WY NE"            "E ROANOKE ST / I5 NB"                  
 [25] "49XX BLOCK OF AURORA AV N"              "15 AV E / E REPUBLICAN ST"             
 [27] "5XX BLOCK OF 15 AV E"                   "E HAMLIN ST / EASTLAKE AV E"           
 [29] "71XX BLOCK OF 12 AV NE"                 "VALLEY ST / FAIRVIEW AV N"             
 [31] "7XX BLOCK OF BROADWAY E"                "SUNNYSIDE AV N / E GREEN LAKE DR N"    
 [33] "NE 95 ST / 35 AV NE"                    "85XX BLOCK OF 20 AV NE"                
 [35] "N 48 ST / GREENWOOD AV N"               "80XX BLOCK OF SAND POINT WY NE"        
 [37] "41 AV E / E BLAINE ST"                  "84XX BLOCK OF 35 AV NE"                
 [39] "23XX BLOCK OF 24 AV E"                  "50XX BLOCK OF UNIVERSITY WY NE"        
 [41] "4XX BLOCK OF 15 AV E"                   "E MONTLAKE PL E / E LAKE WASHINGTON BV"
 [43] "14XX BLOCK OF NE 43 ST"                 "3XX BLOCK OF NICKERSON ST"             
 [45] "16XX BLOCK OF INTERLAKEN PL E"          "91XX BLOCK OF ROOSEVELT WY NE"         
 [47] "8XX BLOCK OF NE 66 ST"                  "22XX BLOCK OF E MADISON ST"            
 [49] "44XX BLOCK OF 52 AV NE"                 "NE 47 ST / 17 AV NE"                   
 [51] "4 AV N / QUEEN ANNE DR"                 "N 90 ST / MERIDIAN AV N"               
 [53] "4XX BLOCK OF BOYLSTON AV E"             "11XX BLOCK OF FAIRVIEW AV N"           
 [55] "45XX BLOCK OF 16 AV NE"                 "FLORENTIA ST / NICKERSON ST"           
 [57] "42XX BLOCK OF WHITMAN AV N"             "47XX BLOCK OF UNIVERSITY WY NE"        
 [59] "NE 50 ST / 9 AV NE"                     "45XX BLOCK OF 25 AV NE"                
 [61] "61XX BLOCK OF BROOKLYN AV NE"           "AURORA AV N / N 68 ST"                 
 [63] "E GALER ST / FRANKLIN AV E"             "45XX BLOCK OF UNIVERSITY WY NE"        
 [65] "AURORA BR / NB"                         "15 AV NE / NE 55 ST"                   
 [67] "10XX BLOCK OF E THOMAS ST"              "NE 45 ST / 11 AV NE"                   
 [69] "2 AV NE / NE 50 ST"                     "11 AV NE / NE 42 ST"                   
 [71] "NE BLAKELEY ST / 25 AV NE"              "25XX BLOCK OF E ROY ST"                
 [73] "4213 1 / 2 UNIVERSITY WY NE"            "15 AV NE / NE 42 ST"                   
 [75] "73XX BLOCK OF ROOSEVELT WY NE"          "NE 47 ST / 9 AV NE"                    
 [77] "AURORA AV N / FREMONT WY N"             "YALE AV N / MERCER ST"                 
 [79] "NE 45 ST / 5 AV NE"                     "NE 52 ST / 15 AV NE"                   
 [81] "47XX BLOCK OF 30 AV NE"                 "AURORA BR / SB"                        
 [83] "UNIVERSITY WY NE / NE 56 ST"            "22XX BLOCK OF E MADISON ST"            
 [85] "ROOSEVELT WY NE / NE 45 ST"             "50XX BLOCK OF UNIVERSITY WY NE"        
 [87] "41XX BLOCK OF UNIVERSITY WY NE"         "27XX BLOCK OF MONTLAKE BV E"           
 [89] "14XX BLOCK OF N 42 ST"                  "NE WINDERMERE RD / SAND POINT WY NE"   
 [91] "12XX BLOCK OF 15 AV E"                  "3 AV N / NICKERSON ST"                 
 [93] "42XX BLOCK OF UNIVERSITY WY NE"         "35 AV NE / NE 95 ST"                   
 [95] "NE 55 ST / 45 AV NE"                    "24XX BLOCK OF E LOUISA ST"             
 [97] "69XX BLOCK OF 62 AV NE"                 "55XX BLOCK OF NE 58 ST"                
 [99] "37XX BLOCK OF CORLISS AV N"             "E INTERLAKEN BV / LAKE WASHINGTON BV E"
[101] "AURORA BR / SB"                         "AURORA AV N / N 50 ST"                 
[103] "45XX BLOCK OF 18 AV NE"                 "NE 50 ST / 2 AV NE"                    
[105] "NEWTON ST / WESTLAKE AV N"              "WOODLAWN AV N / N 63 ST"               
[107] "AURORA BR / SB"                         "73XX BLOCK OF E GREEN LAKE DR N"       
[109] "38XX BLOCK OF AURORA AV N"              "14 AV E / E JOHN ST"                   
[111] "73XX BLOCK OF 35 AV NE"                 "NE 70 ST / 15 AV NE"                   
[113] "45XX BLOCK OF 25 AV NE"                 "48XX BLOCK OF SAND POINT WY NE"        
[115] "45XX BLOCK OF 9 AV NE"                  "2XX BLOCK OF NW 52 ST"                 
[117] "23 AV E / E MADISON ST"                 "14XX BLOCK OF N 45 ST"                 
[119] "15 AV NE / NE 50 ST"                    "24 AV E / E MONTLAKE PL E"             
[121] "AURORA AV N / BRIDGE WY N"              "AURORA BR / SB"                        
[123] "8XX BLOCK OF NE 42 ST"                  "40XX BLOCK OF UNIVERSITY WY NE"        
[125] "38XX BLOCK OF NE 57 ST"                 "9XX BLOCK OF E ROANOKE ST"             
[127] "4XX BLOCK OF BOYLSTON AV E"             "23XX BLOCK OF EASTLAKE AV E"           
[129] "4XX BLOCK OF BROADWAY E"                "BURKE AV N / N NORTHLAKE WY"           
[131] "5XX BLOCK OF 14 AV E"                   "22XX BLOCK OF NE 51 ST"                
[133] "52XX BLOCK OF 22 AV NE"                 "N 45 ST / BURKE AV N"                  
[135] "LATONA AV NE / NE 58 ST"                "12XX BLOCK OF 15 AV E"                 
[137] "15 AV E / E REPUBLICAN ST"              "1 AV NE / N 56 ST"                     
[139] "ROOSEVELT WY NE / NE 65 ST"             "43XX BLOCK OF UNIVERSITY WY NE"        
[141] "85XX BLOCK OF ASHWORTH AV N"            "50XX BLOCK OF 19 AV NE"                
[143] "11XX BLOCK OF FAIRVIEW AV N"            "5XX BLOCK OF BROADWAY E"               
[145] "EASTLAKE AV E / E BOSTON ST"            "34XX BLOCK OF EVANSTON AV N"           
[147] "15 AV NE / NE 50 ST"                    "7XX BLOCK OF N 35 ST"                  
[149] "22 AV E / E MILLER ST"                  "FAIRVIEW AV N / FAIRVIEW AV E"         
[151] "50XX BLOCK OF RAVENNA AV NE"            "52XX BLOCK OF 15 AV NE"                
[153] "55XX BLOCK OF 17 AV NE"                 "39 AV NE / NE 55 ST"                   
control <- rfeControl(functions = rfFuncs, method="cv", number=10)
results <- rfe(frame, out.factor, sizes = c(1:13), rfeControl = control) # this will take AWHILE...
Error in { : task 1 failed - "Can't have empty classes in y."
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3Igc2V0dXB9CiMgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIik7CiMgaW5zdGFsbC5wYWNrYWdlcygicmdkYWwiKTsKbGlicmFyeSh0aWR5dmVyc2UpCnJlcXVpcmUoIm1hcHMiKQpsaWJyYXJ5KGdlb3NwaGVyZSkKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHJnZGFsKQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KGx1YnJpZGF0ZSkKaWYgKCFyZXF1aXJlKGdnbWFwKSkgeyBpbnN0YWxsLnBhY2thZ2VzKCdnZ21hcCcpOyByZXF1aXJlKGdnbWFwKSB9CnBhdGgudG8uY3N2IDwtICcuLi9NaWxlc3RvbmUgMi9TZWF0dGxlX1BvbGljZV9EZXBhcnRtZW50XzkxMV9JbmNpZGVudF9SZXNwb25zZV9PY3QxNy5jc3YnCnNwZC45MTEgPC0gcmVhZC5jc3YocGF0aC50by5jc3YsIFRSVUUpCgpzcGQuOTExJGNsZWFyYW5jZV9kYXRlX3RzID0gYXMuUE9TSVhjdChzdHJwdGltZShzcGQuOTExJEV2ZW50LkNsZWFyYW5jZS5EYXRlLCAiJW0vJWQvJVkgJUk6JU06JVMgJXAiKSkKc3BkLjkxMSRjbGVhcmFuY2VfZGF0ZV9kYXRlID0gYXMuRGF0ZShzcGQuOTExJGNsZWFyYW5jZV9kYXRlX3RzKQojIFZpZXcoc3BkLjkxMSkKCgoKIyBwYXRoIHRvIHRoZSBGT0xERVIgd2l0aCB0aGUgLnNocCBmaWxlIGluIGl0LiB0aGUgc2Vjb25kIHBhcmFtIGlzIHRoZSBuYW1lIG9mIHRoZSAuc2hwIGZpbGUKIyBzZWF0dGxlIDwtIHJlYWRPR1IoZHNuID0gcGF0aC5leHBhbmQoIn4vZG9jdW1lbnRzL0lORk8zNzAvcHJvamVjdC10ZWFtbmFtZS12Mi9tYXBzLWFwaS10ZXN0IiksIGxheWVyID0gIlNlYXR0bGVfQ2l0eV9MaW1pdHMiKQoKIyB1c2EgPC0gbWFwX2RhdGEoInN0YXRlIikKIyBkYXRhIDwtIG1lcmdlKHVzYSwgc3BkLjkxMSkKaGVyZV9sb25nIDwtICAtMTIyLjMwCmhlcmVfbGF0IDwtIDQ3LjY2CgpzZWF0dGxlID0gZ2V0X21hcChsb2NhdGlvbiA9IGMoaGVyZV9sb25nLCBoZXJlX2xhdCksIHpvb20gPSAxMywgbWFwdHlwZSA9ICdyb2FkbWFwJykKCmBgYAoKCmBgYHtyfQpzcGQuOTExIDwtIHNwZC45MTEgJT4lIAogICAgICAgICAgICAgcm93d2lzZSgpICU+JSAKICAgICAgICAgICAgIG11dGF0ZShkaXN0PWRpc3RWaW5jZW50eUVsbGlwc29pZChjKExvbmdpdHVkZSwgTGF0aXR1ZGUpLCBjKGhlcmVfbG9uZywgaGVyZV9sYXQpKSkgICAgICAgICAgICAgIApucm93KHNwZC45MTEpCgpkZXNjcmlwdGlvbnMgPC0gYygiU1RST05HIEFSTSBST0JCRVJZIiwgIlBFUlNPTiBXSVRIIEEgV0VBUE9OIChOT1QgR1VOKSIsICJIQVpBUkRTIiwgIkhBUlJBU01FTlQsIFRIUkVBVFMiLCAiRklHSFQgRElTVFVSQkFOQ0UiLCAiQ1JJU0lTIENPTVBMQUlOVCAtIEdFTkVSQUwiLCAiQVJNRUQgUk9CQkVSWSIpCgpkYXRhLnBlZCA8LSBzcGQuOTExICU+JSBmaWx0ZXIoc3RyX2RldGVjdChFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24sIHBhc3RlKGRlc2NyaXB0aW9ucywgY29sbGFwc2U9InwiKSkpCiMgZGF0YS5wZWQgPC0gZGF0YS5ub3cKbnJvdyhkYXRhLnBlZCkKCmRhdGEubm93IDwtIGRhdGEucGVkICU+JSBmaWx0ZXIoY2xlYXJhbmNlX2RhdGVfdHMgPCAnMjAxNy0xMC0zMSAwMDowMDowMCcpCm5yb3coZGF0YS5ub3cpCiAgICAgICAgICAgICAgICAgIApkYXRhLmhlcmUgPC0gZGF0YS5ub3cgJT4lIGZpbHRlcihkaXN0IDwgNDYwMCkKCmRhdGEgPC0gZGF0YS5oZXJlCm5yb3coZGF0YSkKIyBWaWV3KGRhdGEpCgpnZ21hcChzZWF0dGxlKSArCiAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpLCBjb2xvdXIgPSAicmVkIiwgYWxwaGEgPSAwLjc1KQogICNjb29yZF9tYXAoKQoKYGBgCgpgYGB7cn0KZnJlcV9ieV9kZXNjIDwtIHRhYmxlKGRyb3BsZXZlbHMoZGF0YSRFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24pKQojIFZpZXcoZnJlcV9ieV9kZXNjKQoKZ2dwbG90KGFzLmRhdGEuZnJhbWUoZnJlcV9ieV9kZXNjKSwgCiAgICAgICBhZXMoeCA9IFZhcjEsIHkgPSBGcmVxKSkgKwogICAgICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsjIGNyZWF0ZSBiYXIgcGxvdAogICAgY29vcmRfZmxpcCgpCgojVHJhZmZpYyByZWxhdGVkIGNhbGxzLCBzdXNwaWNpb3VzIGNpcmN1bXN0YW5jZXMsIGFuZCBkaXN0dXJiYW5jZXMgYXJlIHRoZSB0aGUgbW9zdCBzaWduaWZpY2FudCB0aHJlYXRzIHRvIHBlZGVzdHJhdGlvbnMKCiAgICAgICAgCmBgYAoKYGBge3J9CmdnbWFwKHNlYXR0bGUpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCBhZXMoeCA9IExvbmdpdHVkZSwgeSA9IExhdGl0dWRlLCBncm91cCA9IEV2ZW50LkNsZWFyYW5jZS5EZXNjcmlwdGlvbiwgY29sb3IgPSBFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24pLCBhbHBoYSA9IDAuNSkgKwogIGZhY2V0X3dyYXAofiBFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24pICsKICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICAgICAgICApCmBgYAoKYGBge3J9CiMgc2VsZWN0aW5nIGp1c3QgSUQgYW5kIGxvY2F0aW9uIGRhdGEKZGZfbG9jIDwtIGRhdGEgJT4lIGRwbHlyOjpzZWxlY3QoQ0FELkNEVy5JRCwgTG9uZ2l0dWRlLCBMYXRpdHVkZSkKCiMgZmlndXJpbmcgb3V0IG51bWJlciBvZiBjbHVzdGVycwp3c3MgPC0gYygpCiMgY2x1c3RlcnMgMSB0byAxNQpmb3IgKGkgaW4gMToxNSkgewogIHdzc1tpXSA8LSBzdW0oa21lYW5zKGRmX2xvYywgY2VudGVycz1pKSR3aXRoaW5zcykKfQpwbG90KDE6MTUsIHdzcywgdHlwZT0iYiIsIHhsYWI9Ik51bWJlciBvZiBDbHVzdGVycyIsCiAgeWxhYj0iV2l0aGluIGdyb3VwcyBzdW0gb2Ygc3F1YXJlcyIpCgojIGZpdHRpbmcgbW9kZWwKZml0IDwtIGttZWFucyhkZl9sb2MsIDEwKQpmaXQkY2VudGVycyAjIGxvb2sgYXQgY2x1c3RlciBzaXplcyBhbmQgbWVhbnMuIHdhbnQgY2x1c3RlcnMgdG8gYmUgYWJvdXQgZXF1YWwgc2l6ZQpmaXQkY2x1c3RlcgpjbHVzdGVyLnNpemUgPC0gZGF0YS5mcmFtZSgxOjEwLCBmaXQkc2l6ZSkKY2x1c3Rlci5zaXplCgpnZ3Bsb3QoZGF0YSA9IGNsdXN0ZXIuc2l6ZSwgYWVzKHggPSBYMS4xMCwgeSA9IGZpdC5zaXplKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKQpnZ3Bsb3QoKQpnZ21hcChzZWF0dGxlKSArCiAgZ2VvbV9wb2ludChkYXRhID0gYXMuZGF0YS5mcmFtZShmaXQkY2VudGVycyksIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpLCBhbHBoYSA9IDAuNSkKIyBsb29raW5nIGF0IGNsdXN0ZXIgbWVhbnMKYWdncmVnYXRlKGRmX2xvYywgYnk9bGlzdChmaXQkY2x1c3RlciksIEZVTj1tZWFuKQoKZGZfbG9jCgojIGFkZGluZyBkYXRhIGJhY2sgaW50byBkYXRhZnJhbWUgCiMgZGZfbG9jIDwtIGRmX2xvYyAlPiUgbXV0YXRlKGNsdXN0ZXIgPSBmaXQkY2x1c3RlcikgCmRhdGEkY2x1c3RlciA8LSBmaXQkY2x1c3RlcgoKIyBWaWV3KGRhdGEpCmBgYAoKYGBge3J9CiMgdGltZXN0YW1wIC0+ICB5ZWFyICBtb250aCBkYXkgaG91ciAgbWludXRlCiMgc2VjdG9yIC0+IHRvIGZhY3RvciAodGhlcmUgYXJlIDE3IHNlY3RvcnMpCiMgYmVhdCAtPiB0byBmYWN0b3IgKHRoZXJlIGFyZSAzIGJlYXRzIHBlciBzZWN0b3IpCgojIGNsZWFuIHRoZSBkYXRhIGEgYml0IG1vcmUKZGF0YSRldmVudF9jbGVhcmFuY2VfdHMgPSBhcy5QT1NJWGN0KHN0cnB0aW1lKGRhdGEkRXZlbnQuQ2xlYXJhbmNlLkRhdGUsICIlbS8lZC8lWSAlSTolTTolUyAlcCIpKQpkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXRlID0gYXMuRGF0ZShkYXRhJGV2ZW50X2NsZWFyYW5jZV90cykKZGF0YSRldmVudF9jbGVhcmFuY2VfbW9udGggPSBtb250aCh5bWRfaG1zKGFzLmNoYXJhY3RlcihkYXRhJGV2ZW50X2NsZWFyYW5jZV90cykpKQpkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXkgPSB3ZWVrZGF5cyhkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXRlKQpkYXRhJGV2ZW50X2NsZWFyYW5jZV9ociA9IGhvdXIoeW1kX2htcyhhcy5jaGFyYWN0ZXIoZGF0YSRldmVudF9jbGVhcmFuY2VfdHMpKSkKZGF0YSRldmVudF9jbGVhcmFuY2VfbW4gPSBtaW51dGUoeW1kX2htcyhhcy5jaGFyYWN0ZXIoZGF0YSRldmVudF9jbGVhcmFuY2VfdHMpKSkKZGF0YSRJbml0aWFsLlR5cGUuR3JvdXAgPSBmYWN0b3IoZGF0YSRJbml0aWFsLlR5cGUuR3JvdXApCmRhdGEkRXZlbnQuQ2xlYXJhbmNlLkdyb3VwID0gZmFjdG9yKGRhdGEkRXZlbnQuQ2xlYXJhbmNlLkdyb3VwKQpkYXRhJFpvbmUuQmVhdCA9IGZhY3RvcihkYXRhJFpvbmUuQmVhdCkKZGF0YSREaXN0cmljdC5TZWN0b3IgPSBmYWN0b3IoZGF0YSREaXN0cmljdC5TZWN0b3IpCmRhdGEkZXZlbnRfY2xlYXJhbmNlX2RheSA9IGZhY3RvcihkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXkpCmRhdGEKCmNvbC5uYW1lcyA8LSBwYXN0ZShjKAogICJFdmVudC5DbGVhcmFuY2UuQ29kZSIKICAsICJjbHVzdGVyIgogICwgIkNlbnN1cy5UcmFjdCIKICAsICJldmVudF9jbGVhcmFuY2VfZGF5IgogICwgIkV2ZW50LkNsZWFyYW5jZS5Hcm91cCIKICAsICJFdmVudC5DbGVhcmFuY2UuU3ViR3JvdXAiCiAgLCAiRGlzdHJpY3QuU2VjdG9yIgogICwgIlpvbmUuQmVhdCIKICAjLCAiZXZlbnRfY2xlYXJhbmNlX3RzIgogICMgLCJJbmNpZGVudC5Mb2NhdGlvbiIKICAsICJldmVudF9jbGVhcmFuY2VfaHIiCiAgLCAiZXZlbnRfY2xlYXJhbmNlX21uIgogICwgImV2ZW50X2NsZWFyYW5jZV9tb250aCIgCiAgLCAiSHVuZHJlZC5CbG9jay5Mb2NhdGlvbiIKICApLCBjb2xsYXBzZT0ifCIpCmNvbHMgPC0gZ3JlcChjb2wubmFtZXMsIGNvbG5hbWVzKGRhdGEpKQpjb2xzCiMgY29ycl9tYXRyaXggPC0gY29yKGRhdGFbLGNvbHNdKSAjIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGFsbCBwcmVkaWN0b3IgdmFycwojIGNvcnJfbWF0cml4CgojIGN1dG9mZiA8LSAwLjUgIyBzaG91bGQgYmUgaGlnaGVyIGluIHByYWN0aWNlCgojIGhpZ2hseV9jb3JyIDwtIGZpbmRDb3JyZWxhdGlvbihjb3JyX21hdHJpeCwgY3V0b2ZmPWN1dG9mZikKIyBwcmludChjb2xuYW1lcyhzcGQuOTExKVtoaWdobHlfY29ycl0pICMgYWdlIGlzIGhpZ2hseSBjb3JyZWFsdGVkIHdpdGggcHJlZ25hbnQKCnRyYWluLmRhdGEgPC0gc2VsZWN0KGRhdGEsIGNvbHMpCnRyYWluLmRhdGEKIyBkYXRhIDwtIGRhdGEgJT4lIGRyb3BsZXZlbHMoKQoKIyBncmVwKCJIdW5kcmVkLkJsb2NrLkxvY2F0aW9uIiwgY29sbmFtZXModHJhaW4uZGF0YSksIGludmVydCA9IFQpCgpwcmVkaWN0b3JzIDwtIGdyZXAoIkh1bmRyZWQuQmxvY2suTG9jYXRpb24iLCBjb2xuYW1lcyh0cmFpbi5kYXRhKSwgaW52ZXJ0ID0gVCkKb3V0Y29tZSA8LSBncmVwKCJIdW5kcmVkLkJsb2NrLkxvY2F0aW9uIiwgY29sbmFtZXModHJhaW4uZGF0YSkpCgojIHRyYWluLmRhdGFbLHByZWRpY3RvcnNdCmZyYW1lIDwtIGRhdGEuZnJhbWUodHJhaW4uZGF0YVsscHJlZGljdG9yc10pCmZyYW1lCm91dC5mYWN0b3IgPC0gdHJhaW4uZGF0YSRIdW5kcmVkLkJsb2NrLkxvY2F0aW9uCmFzLnZlY3RvcihvdXQuZmFjdG9yKQoKCmNvbnRyb2wgPC0gcmZlQ29udHJvbChmdW5jdGlvbnMgPSByZkZ1bmNzLCBtZXRob2Q9ImN2IiwgbnVtYmVyPTEwKQpyZXN1bHRzIDwtIHJmZShmcmFtZSwgb3V0LmZhY3Rvciwgc2l6ZXMgPSBjKDE6MTMpLCByZmVDb250cm9sID0gY29udHJvbCkgIyB0aGlzIHdpbGwgdGFrZSBBV0hJTEUuLi4KCnJlc3VsdHMKZ2dwbG90KHJlc3VsdHMpCgojIGNob3NlbiBmZWF0dXJlcwpwcmVkaWN0b3JzKHJlc3VsdHMpCmBgYAo=